﻿using System;
using System.IO;
using System.Management;

namespace Brjnk.Common
{
    /// <summary>
    /// Objekt sleduje připojení a odpojení datových úložišť (FlashDisk atd.)
    /// </summary>
    public class DiskConnectedWatcher
    {
        private System.Management.ManagementEventWatcher watcherConnect;
        private System.Management.ManagementEventWatcher watcherDisconnect;

        public DiskConnectedWatcher()
        {
            //Within definuje časový interval kontroly nové události
            watcherConnect = new System.Management.ManagementEventWatcher("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_LogicalDisk'");
            watcherConnect.EventArrived += new System.Management.EventArrivedEventHandler(Connected);
            watcherConnect.Start();

            watcherDisconnect = new System.Management.ManagementEventWatcher("SELECT * FROM __InstanceDeletionEvent WITHIN 20 WHERE TargetInstance ISA 'Win32_LogicalDisk'");
            watcherDisconnect.EventArrived += new EventArrivedEventHandler(Disconnected);
            watcherDisconnect.Start();

            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);

            diskTypes = (DiskTypes)int.MaxValue;
        }

        private void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            watcherConnect.Dispose();
            watcherDisconnect.Dispose();
        }

        private void Disconnected(object sender, EventArrivedEventArgs e)
        {
            System.Management.ManagementBaseObject p = e.NewEvent.Properties["TargetInstance"].Value as System.Management.ManagementBaseObject;
            DriveInfo di = new DriveInfo(p.Properties["Name"].Value.ToString());

            if (((int)Math.Pow((double)2, (double)di.DriveType) & (int)diskTypes) > 0)
            {
                if (DiskDisconnected != null) DiskDisconnected(di);
            }
        }

        private void Connected(object sender, EventArrivedEventArgs e)
        {
            System.Management.ManagementBaseObject p = e.NewEvent.Properties["TargetInstance"].Value as System.Management.ManagementBaseObject;
            DriveInfo di = new DriveInfo(p.Properties["Name"].Value.ToString());

            if (((int)Math.Pow((double)2, (double)di.DriveType) & (int)diskTypes) > 0)
            {
                if (DiskConnected != null) DiskConnected(di);
            }
        }

        public delegate void DiskConnectedEventHandler(DriveInfo driveInfo);

        public event DiskConnectedEventHandler DiskConnected;

        public event DiskConnectedEventHandler DiskDisconnected;

        private DiskTypes diskTypes;

        public DiskTypes DiskTypesFilter
        {
            get { return diskTypes; }
            set { diskTypes = value; }
        }
    }

    [Flags()]
    public enum DiskTypes : int
    {
        // Summary:
        //     The type of drive is unknown.
        Unknown = 1,

        //
        // Summary:
        //     The drive does not have a root directory.
        NoRootDirectory = 2,

        //
        // Summary:
        //     The drive is a removable storage device, such as a floppy disk drive or a
        //     USB flash drive.
        Removable = 4,

        //
        // Summary:
        //     The drive is a fixed disk.
        Fixed = 8,

        //
        // Summary:
        //     The drive is a network drive.
        Network = 16,

        //
        // Summary:
        //     The drive is an optical disc device, such as a CD or DVD-ROM.
        CDRom = 32,

        //
        // Summary:
        //     The drive is a RAM disk.
        Ram = 64,
    }
}